package com.springboot.common.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 日期
 *
 * <p>
 * 修改了SimpleDateFormat线程不安全的问题，弃用以前的写法 采用新的写法
 */
public class DateUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtils.class);

    /**
     * 时间分隔符
     */
    private static final String SEPARATOR = ":";
    private static final String MINUS = "-";

    public static final String DATE_FORMAT_HOUR_MIN_5 = "HH:mm";
    public static final String DATE_FORMAT_HOUR_MIN_SEC_8 = "HH:mm:ss";
    public static final String DATE_FORMAT_MIN_SEC = "mm:ss";
    public static final String DATE_FORMAT_YEAR = "yyyy";
    public static final String DATE_FORMAT_MONTH = "MM";
    public static final String DATE_FORMAT_DAY = "dd";
    public static final String DATE_FORMAT_6 = "yyyyMM";
    public static final String DATE_FORMAT_7 = "yyyy-MM";
    public static final String DATE_FORMAT_8 = "yyyyMMdd";
    public static final String DATE_FORMAT_10 = "yyyy-MM-dd";
    public static final String DATE_FORMAT_10_SLASH = "yyyy/MM/dd";
    public static final String DATE_FORMAT_11_IN_CHINESE = "yyyy年MM月dd日";
    public static final String DATE_FORMAT_13 = "yyyy-MM-dd HH";
    public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss";
    public static final String DATE_FORMAT_WITH_NO_SEPARATOR_TO_MILLI = "yyyyMMddHHmmssSSS";
    public static final String DATE_FORMAT_17_IN_CHINESE = "yyyy年MM月dd日HH时mm分";
    public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_WITH_MILLISECOND = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_FORMAT_17 = "yyyy-MM-dd HH:mm";
    public static final String DATE_FORMAT_SSS_17 = "yyyyMMddHHmmssSSS";

    private static final int SECOND_TIMESTAMP = 1000;
    private static final int MINUTE_TIMESTAMP = 60 * SECOND_TIMESTAMP;
    private static final int HOUR_TIMESTAMP = 60 * MINUTE_TIMESTAMP;
    /**
     * 支持时间戳转换的格式
     */
    private static final Set<String> SUPPORT_TIMESTAMP_SPAN_CONVERT_FORMAT = new HashSet<>();


    /**
     * 存储线程SimpleDateFormat缓存
     */
    public static final ThreadLocal<Map<String, SimpleDateFormat>> SIMPLE_DATE_FORMAT_THREAD_LOCAL_MAP =
            new ThreadLocal<Map<String, SimpleDateFormat>>() {
                @Override
                protected Map<String, SimpleDateFormat> initialValue() {
                    return new HashMap<>();
                }
            };


    static {
        SUPPORT_TIMESTAMP_SPAN_CONVERT_FORMAT.add(DATE_FORMAT_HOUR_MIN_SEC_8);
        SUPPORT_TIMESTAMP_SPAN_CONVERT_FORMAT.add(DATE_FORMAT_HOUR_MIN_5);
    }

    private DateUtils() {
    }

    /**
     * 去本地线程获取SimpleDateFormat 如果存在则返回，不存在 则创建
     *
     * @param dateformat
     * @return
     
     */
    private static DateFormat getDateFormat(final String dateformat) {
        Map<String, SimpleDateFormat> simpleDateFormatMap = SIMPLE_DATE_FORMAT_THREAD_LOCAL_MAP.get();
        if (simpleDateFormatMap.containsKey(dateformat)) {
            return simpleDateFormatMap.get(dateformat);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateformat);
        simpleDateFormatMap.put(dateformat, simpleDateFormat);
        return simpleDateFormat;
    }

    /**
     * 将一个String转换根据指定格式转换成日期
     *
     * @param dateString
     * @param dateFormat
     * @return 不会抛出异常，但是如果转换错误，返回对象可能为null 请自行判断
     
     */
    public static Date parseDate(final String dateString, final String dateFormat) {
        if (StringUtil.isEmpty(dateString)) {
            return null;
        }
        try {
            return getDateFormat(dateFormat).parse(dateString);
        } catch (Exception e) {
            LOGGER.warn("日期格式转换异常，日期字符串为:{}，转换格式为:{}", dateString, dateFormat, e);
        }
        return null;
    }

    /**
     * 将任何String类型的日期转换为日期，不抛出异常,如果遇到不兼容的格式 建议直接加进来
     *
     * <p>
     * 目前支持如下格式：
     * <li>1.yyyy-MM-dd HH:mm:ss
     * <li>2.yyyy-MM-dd
     * <li>3.yyyyMMddHHmmss
     * <li>4.yyyyMMdd
     * <li>5.yyyyMM
     *
     * @param dateStr 必须是24h的日期格式 如果不是 需要修改此方法
     * @return 如果异常 则输出warn且返回null
     
     */
    public static Date parseDate(String dateStr) {
        if (StringUtil.isEmpty(dateStr)) {
            return null;
        }
        String dateStrTrim = dateStr.trim();
        int length = dateStrTrim.length();
        // 如果长度不对 直接返回空
        if (length != 19 && length != 14 && length != 10 && length != 8 && length != 6 && length != 16) {
            return null;
        }
        try {
            if (StringUtils.contains(dateStrTrim, MINUS) && (length == 19 || length == 10)) {
                if (StringUtils.contains(dateStrTrim, SEPARATOR) && length == 19) {
                    return parseDate(dateStrTrim, DATE_FORMAT_19);
                }
                if (length == 10) {
                    return parseDate(dateStrTrim, DATE_FORMAT_10);
                }
                return null;
            }
            if (length == 14) {
                return parseDate(dateStrTrim, DATE_FORMAT_14);
            }
            if (length == 8) {
                return parseDate(dateStrTrim, DATE_FORMAT_8);
            }
            if (length == 6) {
                return parseDate(dateStrTrim, DATE_FORMAT_6);
            }
            if(length == 16){
                return parseDate(dateStrTrim,DATE_FORMAT_17);
            }
        } catch (Exception e) {
            LOGGER.warn("日期格式转换异常,转换的日期Str:{}", dateStr, e);
        }
        return null;
    }

    /**
     * 校验日期格式是否正确 注意 空格可以识别 然后 年份可能不是4位
     *
     * <pre>
     * DateUtils.isDate("2017-01-01","yyyy-MM-dd")       = true
     * DateUtils.isDate("  2017-01-01  ","yyyy-MM-dd")   = true
     * DateUtils.isDate(" 20113-01-01 ","yyyy-MM-dd")    = true
     * DateUtils.isDate("2017-01-01d","yyyy-MM-dd")      = false
     * DateUtils.isDate("2017-13-01","yyyy-MM-dd")       = false
     * </pre>
     *
     * @param dateString
     * @param dateformat
     * @return
     
     */
    public static boolean isDate(final String dateString, final String dateformat) {
        return isDate(dateString, dateformat, false);
    }

    /**
     * 校验日期格式是否正确 如果为lengthCheck=true, 必须dateString的长度等于dateformat的长度,如果有空格，也不会忽略
     * <p>
     * 这里需要注意 如果年多了一位 日期少了一位 也会显示true
     *
     * <pre>
     * DateUtils.isDate("2017-01-01","yyyy-MM-dd",true)       = true
     * DateUtils.isDate("20173-01-1","yyyy-MM-dd",true)       = true
     * DateUtils.isDate("20113-01-01","yyyy-MM-dd",true)      = false
     * DateUtils.isDate("  2017-01-01  ","yyyy-MM-dd",true)   = false
     * DateUtils.isDate(" 20113-01-01 ","yyyy-MM-dd",true)    = false
     * DateUtils.isDate("2017-01-01d","yyyy-MM-dd",true)      = false
     * DateUtils.isDate("2017-13-01","yyyy-MM-dd",true)       = false
     * </pre>
     *
     * @param dateString
     * @param dateformat
     * @return
     
     */
    public static boolean isDate(final String dateString, final String dateformat, boolean lengthCheck) {
        /*boolean isDate = DateValidator.getInstance().isValid(dateString, dateformat);
        if (!lengthCheck) {
            return isDate;
        }
        return isDate && dateString.length() == dateformat.length();*/
        return true;
    }


    /**
     * 校验dateString是否符合dateformat 并返回 dateString.trim() 并且 如果返回的长度不是需要的长度 则重新格式化过
     * <p>
     * 简单的说，解决了如下问题
     * <li>1.防止不符合dateformat格式的存入数据库
     * <li>2.去dateString的空格
     * <li>3.由于2017-1-1也是符合yyyy-MM-dd 格式的，会帮忙变成2017-01-01
     * <li>4.无法解决的问题：由于20171-01-1也是符合yyyy-MM-dd 格式的，但是长度也刚好是10，所以不会出区里这样的数据
     *
     * <pre>
     * DateUtils.formatDate("2017-01-01","yyyy-MM-dd",null)         = "2017-01-01"
     * DateUtils.formatDate("  2017-01-01  ","yyyy-MM-dd",null)     = "2017-01-01"
     * DateUtils.formatDate("  20173-01-01  ","yyyy-MM-dd",null)    = "20173-01-01"
     * DateUtils.formatDate("  20173-01-1  ","yyyy-MM-dd",null)     = "20173-01-1"
     * DateUtils.formatDate("  2017-1-1  ","yyyy-MM-dd",null)       = "2017-01-01"
     * </pre>
     *
     * @param dateString
     * @param dateFormat
     * @param defaultString
     * @return 如果遇到空 则返回空字符串
     
     */
    public static String formatDate(String dateString, String dateFormat, String defaultString) {
        if (isDate(dateString, dateFormat)) {
            String dateStringTrim = dateString.trim();
            // 如果长度不相等 很可能是 2017-1-1符合 yyyy-MM-dd的情况
            if (dateStringTrim.length() != dateFormat.length()) {
                // 这里将 String 转成date 再转成string 会将 2017-1-1变成 2017-01-01
                return formatDate(parseDate(dateStringTrim, dateFormat), dateFormat);
            }
            return dateStringTrim.trim();
        }
        return defaultString;
    }

    /**
     * 根据日期返回对应的日期格式
     *
     * @param date
     * @return 如果遇到空 则返回空字符串
     
     */
    public static String formatDate(Date date) {
        return formatDate(date, DateUtils.DATE_FORMAT_19);
    }


    /**
     * 根据日期返回对应的日期格式
     *
     * @param date
     * @param dateFormat
     * @return 如果遇到空 则返回空字符串
     
     */
    public static String formatDate(Date date, String dateFormat) {
        return formatDate(date, dateFormat, "");
    }

    /**
     * 根据日期返回对应的日期格式
     *
     * @param date
     * @param dateformat
     * @return 如果遇到空 则返回空字符串
     
     */
    public static String formatDate(Date date, String dateformat, String defaultString) {
        if (date == null || StringUtil.isEmpty(dateformat)) {
            return defaultString;
        }
        return getDateFormat(dateformat).format(date);
    }

    /**
     * 日期相差月份 date2 - date1
     *
     * @param startDate
     * @param endDate
     * @param dateformat
     * @return
     */
    public static int getMonthSpace(String startDate, String endDate, String dateformat) {
        DateFormat dateFormat = getDateFormat(dateformat);
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();

        try {
            c1.setTime(dateFormat.parse(startDate));
            c2.setTime(dateFormat.parse(endDate));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        int year = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);

        return year * 12 + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
    }


    /**
     * 当天凌晨 00:00:00
     *
     * @return
     */
    public static Date getEarliestDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        // 将毫秒也设置成 0 防止存入数据库四舍五入变成00:00:01
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 当天半夜23:59:59
     *
     * @return
     */
    public static Date getLatestDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    /**
     * 传入正值，以后时间 传入负值，之前时间
     *
     * @param date
     * @param year
     * @param day
     * @param hour
     * @param minute
     * @return
     */
    public static Date getModifyDate(Date date, int year, int day, int hour, int minute) {
        if (date == null) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(date.getTime());
        c.add(Calendar.YEAR, year);
        c.add(Calendar.DATE, day);// 天后的日期
        c.add(Calendar.HOUR_OF_DAY, hour);
        c.add(Calendar.MINUTE, minute);
        return new Date(c.getTimeInMillis());
    }


    /**
     * 查看日期具体field
     *
     * @param date  日期
     * @param field 同 {@link Calendar} filed定义
     * @return
     */
    public static int getField(Date date, int field) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(field);
    }


    /**
     * 格式化经过的时间 将long时间 显示成 1天1小时1分钟
     *
     * @param time     long格式的时间
     * @param endField 结束的位置 仅仅支持： {@link Calendar#DAY_OF_YEAR} {@link Calendar#HOUR}
     *                 {@link Calendar#MINUTE} {@link Calendar#SECOND}
     * @return
     */
    public static String formatElapsedTime(long time, int endField) {
        return formatElapsedTime(time,endField,null);
    }
    /**
     * 格式化经过的时间 将long时间 显示成 1天1小时1分钟,最大显示日期
     *
     * @param time     long格式的时间
     * @param endField 结束的位置 仅仅支持： {@link Calendar#DAY_OF_YEAR} {@link Calendar#HOUR}
     *                 {@link Calendar#MINUTE} {@link Calendar#SECOND}
     * @return
     */
    public static String formatElapsedTime(long time, int endField,Long maxDay) {
        StringBuilder sb = new StringBuilder();
        // 天
        long day = time / (24 * 60 * 60 * 1000);
        boolean isEnd = endField == Calendar.DAY_OF_YEAR;
        boolean needDay = day > 0 || isEnd;
        if (maxDay != null && day >= maxDay) {
            sb.append(maxDay).append("天");
        } else if (needDay) {
            sb.append(day).append("天");
        }
        if (isEnd) {
            return sb.toString();
        }
        // 小时
        long hour = (time / (60 * 60 * 1000) - day * 24);
        isEnd = endField == Calendar.HOUR;
        boolean needHour = hour > 0 || day > 0 || isEnd;
        if (needHour) {
            sb.append(hour).append("小时");
        }
        if (isEnd) {
            return sb.toString();
        }
        // 分钟
        long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60);
        isEnd = endField == Calendar.MINUTE;
        boolean needMinute = hour > 0 || day > 0 || minute > 0 || isEnd;
        if (needMinute) {
            sb.append(minute).append("分钟");
        }
        if (isEnd) {
            return sb.toString();
        }
        // 秒
        long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);
        // 任何情况 都需要显示秒
        sb.append(second).append("秒");
        return sb.toString();
    }

    /**
     * 时间间隔 转换成指定的格式 目前仅支持 HH:mm 或 HH:mm:ss 的格式
     *
     * @param time
     * @param format 要转换的类型
     * @return
     */
    public static String formatSpanTime(Long time,String format) {
        if (Objects.isNull(time)) {
            return null;
        }
        checkSpanTimestampFormat(format);
        long timestamp = time;
        long hours = timestamp / HOUR_TIMESTAMP;
        timestamp = timestamp - hours * HOUR_TIMESTAMP;
        long minutes = timestamp / MINUTE_TIMESTAMP;
        timestamp = timestamp - minutes * MINUTE_TIMESTAMP;
        long seconds = timestamp / SECOND_TIMESTAMP;
        StringBuilder result = new StringBuilder();
        result.append(StringUtils.leftPad(Long.toString(hours), 2, "0"));
        result.append(SEPARATOR);
        result.append(StringUtils.leftPad(Long.toString(minutes), 2, "0"));
        if(StringUtils.equals(format,DATE_FORMAT_HOUR_MIN_SEC_8)){
            result.append(SEPARATOR);
            result.append(StringUtils.leftPad(Long.toString(seconds), 2, "0"));
        }
        return result.toString();
    }

    /**
     * 指定的格式时间间隔字符串 转换成时间戳 目前仅支持 HH:mm 或 HH:mm:ss 的格式
     *
     * @param timeStamp 指定格式的时间戳字符串  时:分:秒
     * @param format 要转换的类型
     * @return
     */
    public static Long formatSpanTime(String timeStamp,String format) {
        checkSpanTimestampFormat(format);
        if (StringUtils.isBlank(timeStamp)) {
            return null;
        }
        Long result = null;
        String[] times = StringUtils.split(timeStamp,SEPARATOR);
        switch (format) {
            case DATE_FORMAT_HOUR_MIN_SEC_8:
                result = Long.valueOf(times[0]) * HOUR_TIMESTAMP + Long.valueOf(times[1]) * MINUTE_TIMESTAMP + Long.valueOf(times[2]) * SECOND_TIMESTAMP;
                break;
            case DATE_FORMAT_HOUR_MIN_5:
                result = Long.valueOf(times[0]) * HOUR_TIMESTAMP + Long.valueOf(times[1]) * MINUTE_TIMESTAMP;
                break;
            default:
                break;
        }
        return result;
    }

    private static void checkSpanTimestampFormat(String format) {
        if( SUPPORT_TIMESTAMP_SPAN_CONVERT_FORMAT.contains(format)) {
            return;
        }
        throw new UnsupportedOperationException("仅支持以下格式: "+SUPPORT_TIMESTAMP_SPAN_CONVERT_FORMAT);
    }

    /**
     * 明天
     *
     * @return
     */
    public static Date tomorrow() {
        return tomorrow(new Date());
    }

    /**
     * 明天
     *
     * @return
     */
    public static Date tomorrow(Date date) {
        return getModifyDate(date, 0, 1, 0, 0);
    }

    /**
     * 昨天
     *
     * @return
     */
    public static Date yesterday() {
        return yesterday(new Date());
    }

    /**
     * 昨天
     *
     * @param date
     * @return
     */
    public static Date yesterday(Date date) {
        return DateUtils.getModifyDate(date, 0, -1, 0, 0);
    }


    /**
     * 日期相差月份
     *
     * @param starteDate
     * @param endDate
     * @return
     */
    public static int getMonthSpace(Date starteDate, Date endDate) {
        Calendar startCalendar = Calendar.getInstance();
        Calendar endCalendar = Calendar.getInstance();

        startCalendar.setTime(starteDate);
        endCalendar.setTime(endDate);

        int year = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);

        return year * 12 + endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
    }

    /**
     * 日期相差月份，给计算车龄用
     * @param starteDate
     * @param endDate
     * @return
     */
    public static int getMonthSpaceWithCarAge(Date starteDate, Date endDate){
        Calendar startCalendar = Calendar.getInstance();
        Calendar endCalendar = Calendar.getInstance();

        startCalendar.setTime(starteDate);
        endCalendar.setTime(endDate);

        int year = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);

        if (endCalendar.get(Calendar.DAY_OF_MONTH) > startCalendar.get(Calendar.DAY_OF_MONTH)) {
            return year * 12 + endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH) + 1;
        } else {
            return year * 12 + endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
        }
    }

    /**
     * 获取当前日期的日期型变量
     *
     * @return
     */
    public static Date getCurrentDate() {
        return new Date(System.currentTimeMillis());
    }

    /**
     * 根据指定格式获取当前日期
     *
     * @param dateFormat
     * @return
     */
    public static String getCurrentDate(String dateFormat) {
        return formatDate(getCurrentDate(), dateFormat);
    }

    /**
     * 获取当前Calendar 万一需要调整时区等 可以统一调整
     *
     * @return
     */
    public static Calendar currentCalendar() {
        return Calendar.getInstance();
    }

    /**
     * 计算两个日期之间的年份差， 较晚日期的 月日 早于 较早日期的 月日，那么年份差还需减一
     *
     * @param earlierDate
     * @param laterDate
     * @return
     */
    public static int getYearBetweenDate(Date earlierDate, Date laterDate) {
        int earlierYear = getDateYear(earlierDate);
        int laterYear = getDateYear(laterDate);
        int earlierDay = getDayOfYear(earlierDate);
        int laterDay = getDayOfYear(laterDate);
        if (laterDay >= earlierDay) {
            return laterYear - earlierYear;
        } else {
            return laterYear - earlierYear - 1;
        }
    }

    /**
     * 获取时间的所处年份
     *
     * @param date
     * @return
     */
    public static int getDateYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int year = cal.get(Calendar.YEAR);
        return year;
    }

    /**
     * 获取时间的所处月份 1月返回数字1而不是0
     *
     * @param date
     * @return
     */
    public static int getDateMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month = cal.get(Calendar.MONTH);
        return month + 1;
    }


    /**
     * 获取时间的所处小时
     *
     * @param date
     * @return
     */
    public static int getDateHour(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int hour = cal.get(Calendar.HOUR);
        return hour;
    }

    /**
     * 获取时间的所处小时(24小时制)
     *
     * @param date
     * @return
     */
    public static int getDateHour24(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        return hour;
    }

    /**
     * 获取时间的所处分钟
     *
     * @param date
     * @return
     */
    public static int getDateMinuter(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int hour = cal.get(Calendar.MINUTE);
        return hour;
    }
    /**
     * 获取时间的所处一年之中的天数
     *
     * @param date
     * @return
     */
    public static int getDayOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int day = cal.get(Calendar.DAY_OF_YEAR);
        return day;
    }

    /**
     * date之后几个月的时间
     *
     * @param date
     * @param num
     * @return
     */
    public static Date getMonthDate(Date date, int num) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, num);
        return cal.getTime();
    }

    /**
     * 获取date时间所处月份的第一天的00:00:00的时刻
     *
     * @param date
     * @return
     */
    public static Date getMonthStartDate(Date date) {
        Calendar cal = Calendar.getInstance();
        // cal.setTime(date);
        int year = getDateYear(date);
        int month = getDateMonth(date);
        int day = 1;
        cal.set(year, month - 1, day, 0, 0, 0);
        return cal.getTime();
    }

    /**
     * 将日期对象转换成 18 位长 String 日期格式
     *
     * @param date
     * @return
     */
    public static String convertDateToStr(Date date) {
        if (date == null) {
            return null;
        }
        return dateformat_18.format(date);
    }

    /**
     * 判断两个时间的日期是否一致
     *
     * @param date1
     * @param date1
     * @return
     */
    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }
        String day1 = getDateFormat(date1, dateformat_10);
        String day2 = getDateFormat(date2, dateformat_10);

        if (day1.equals(day2)) {
            return true;
        }

        return false;
    }

    /**
     * 获得当天开始时间
     *
     * @return 毫秒
     */
    public static long getTodayBeginTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获得当天结束时间
     *
     * @return 毫秒
     */
    public static long getTodayEndTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获得本周开始时间(周一)
     *
     * @return 毫秒
     */
    public static long getThisWeekBeginTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_WEEK, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获得本周结束时间(周日)
     *
     * @return 毫秒
     */
    public static long getThisWeekEndTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.WEEK_OF_MONTH, 1);
        calendar.set(Calendar.DAY_OF_WEEK, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }


    /***
     * 该方法计算两个日期相隔天数，跟常规的计算方法不同
     * endDate 2018-09-12 10:58:50  减去  startDate 2018-09-11 14:58:20
     * 计算结果为1，日期跨天即为相隔1天，不是两时间的毫秒数之差大于一天的天数
     * @param endDate
     * @param startDate
     * @return
     */
    public static int getDaySpace(Date endDate, Date startDate) {
        Calendar beginCalendar = Calendar.getInstance();
        beginCalendar.setTime(startDate);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);
        long beginTime = beginCalendar.getTime().getTime();
        long endTime = endCalendar.getTime().getTime();
        int betweenDays = (int) ((endTime - beginTime) / (1000 * 60 * 60 * 24));

        endCalendar.add(Calendar.DAY_OF_MONTH, -betweenDays);
        endCalendar.add(Calendar.DAY_OF_MONTH, -1);
        //比较两日期的DAY_OF_MONTH是否相等
        if (beginCalendar.get(Calendar.DAY_OF_MONTH) == endCalendar.get(Calendar.DAY_OF_MONTH)) {
            return betweenDays + 1;
        } else {
            return betweenDays + 0;
        }
    }

    /**
     * 获得本月开始时间
     *
     * @return 毫秒
     */
    public static long getThisMonthBeginTimeStamp() {
        return getMonthBeginTimeStamp(0);
    }

    /**
     * 获得本月结束时间
     *
     * @return 毫秒
     */
    public static long getThisMonthEndTimeStamp() {
        return getMonthEndTimeStamp(0);
    }

    /**
     * 获得以当前月为基准 某个月的开始时间
     *
     * @param monthGap 0表示当前月 -1表示上个月 1表示下个月 依次类推
     * @return
     */
    public static long getMonthBeginTimeStamp(int monthGap) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.MONTH, monthGap);
        return calendar.getTimeInMillis();
    }

    /**
     * 获得以当前月为基准 某个月的结束时间
     *
     * @param monthGap 0表示当前月 -1表示上个月 1表示下个月 依次类推
     * @return
     */
    public static long getMonthEndTimeStamp(int monthGap) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, monthGap + 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获得本小时开始时间
     *
     * @return 毫秒
     */
    public static long getThisHourBeginTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获得本小时结束时间
     *
     * @return 毫秒
     */
    public static long getThisHourEndTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }


    /**
     * 判断一个日期是否在两个日期之间
     * 当三个日期任一为空时，返回false
     * @param targetDate 目标日期
     * @param date1 日期1
     * @param date2 日期2
     * @param equalResult 目标日期与日期1或日期2相等时的返回
     * @return true是，false否
     */
    public static boolean isDateBetween(Date targetDate,Date date1,Date date2,boolean equalResult){
        if(targetDate ==null || date1 == null ||date2 ==null){
            return false;
        }
        if(targetDate.equals(date1) || targetDate.equals(date2)){
            return equalResult;
        }
        Date maxDate = date1.after(date2) ? date1 : date2;
        Date minDate = date1.before(date2) ? date1 : date2;
        return targetDate.after(minDate) && targetDate.before(maxDate);
    }

    /**
     * 统一使用map管理
     */
    @Deprecated
    public static final ThreadLocal<SimpleDateFormat> SIMPLE_DATE_FORMAT_THREAD_LOCAL =
            new ThreadLocal<SimpleDateFormat>() {
                @Override
                protected SimpleDateFormat initialValue() {
                    return new SimpleDateFormat(DATE_FORMAT_18);
                }
            };

    /**
     * 线程不安全，弃用 请用 parseDate
     *
     * @param dateString
     * @param dateformat
     * @return
     
     * @see DateUtils#parseDate(String, String)
     * @deprecated
     */
    @Deprecated
    public static Date getDateByDateFormat(String dateString, SimpleDateFormat dateformat) {
        if (StringUtils.isBlank(dateString) || dateformat == null || dateString.contains("null")) {
            return null;
        }
        try {
            return dateformat.parse(dateString);
        } catch (ParseException e) {
            LOGGER.error("", e);
        }
        return null;
    }


    /**
     * 线程不安全，弃用 请用 isDate
     *
     * @param dateString
     * @param dateformat
     * @return
     
     * @see DateUtils#isDate(String, String)
     * @deprecated
     */
    @Deprecated
    public static boolean validate(String dateString, SimpleDateFormat dateformat) {
        return validate(dateString, dateformat, true);
    }

    /**
     * 线程不安全，弃用 请用 isDate
     *
     * @param dateString
     * @param dateformat
     * @param lengthCheck
     * @return
     
     * @see DateUtils#isDate(String, String, boolean)
     * @deprecated
     */
    @Deprecated
    public static boolean validate(String dateString, SimpleDateFormat dateformat, boolean lengthCheck) {
        if (StringUtils.isBlank(dateString) || dateformat == null) {
            return false;
        }
        ParsePosition parsePosition = new ParsePosition(0);
        dateformat.parse(dateString, parsePosition);

        if (parsePosition.getIndex() <= 0 && parsePosition.getErrorIndex() >= 0) {
            // 日期格式不一致
            return false;
        }

        if (lengthCheck && parsePosition.getIndex() != dateString.length()) {
            // 存在多余字符串
            return false;
        }

        return true;
    }

    /**
     * 按格式输出时间 弃用 请用 formatDate
     *
     * @param date
     * @param dateformat
     * @return
     * @see DateUtils#formatDate(Date, String)
     * @deprecated
     */
    @Deprecated
    public static String getDateFormat(Date date, SimpleDateFormat dateformat) {
        if (date == null || dateformat == null) {
            return null;
        }
        return dateformat.format(date);
    }

    /**
     * 根据给定时间及格式，返回日期型变量 弃用 统一使用 parseDate
     *
     * @param time
     * @param dateFormat
     * @return
     * @throws ParseException
     * @see DateUtils#parseDate(String, String)
     * @deprecated
     */
    @Deprecated
    public static Date parseStringToDate(String time, SimpleDateFormat dateFormat) throws ParseException {
        return dateFormat.parse(time);
    }

    /**
     * 默认使用 dateformat_18 来解析字符串为日期型变量 弃用 使用 parseDate
     *
     * @param time
     * @return
     * @throws ParseException
     * @see DateUtils#parseDate(String, String)
     * @deprecated
     */
    @Deprecated
    public static Date parseStringToDate(String time) throws ParseException {
        return dateformat_18.parse(time);
    }

    /**
     * 获取时间的所处月中的天数
     *
     * @param date
     * @return
     */
    public static int getDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int day = cal.get(Calendar.DAY_OF_MONTH);
        return day;
    }

    /**
     * 获取时间的所处月份 1月返回01而不是1
     *
     * @param date
     * @return
     */
    public static String getDateMonthStr(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month = cal.get(Calendar.MONTH) + 1;
        if (month < 10 ){
            return "0" + month;
        }
        return String.valueOf(month);
    }


    public static int differentDaysByMillisecond(Date date1, Date date2) {
        int days = (int) ((date1.getTime() - date2.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    /**
     * 计算2个日期相差天数，日期比对仅精确到日
     * 
     * @param endDate
     * @param beginDate
     * @return
     */
    public static int differentDaysByDay(Date endDate, Date beginDate) {
        Calendar endCalendar = buildDateCalendar(endDate);
        Calendar beginCalendar = buildDateCalendar(beginDate);
        return DateUtils.differentDaysByMillisecond(endCalendar.getTime(), beginCalendar.getTime());
    }


    private static Calendar buildDateCalendar(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    

    /**
     * 获取下一年时间 -1天
     *
     * @param cinTime
     * @return
     */
    public static String getNextYear(String cinTime) {
        Calendar cal = Calendar.getInstance();
        try {
            cal.setTime(getDateFormat(DATE_FORMAT_19).parse(cinTime));
        } catch (ParseException e) {
            return "";
        }
        cal.add(Calendar.YEAR, 1);
        cal.add(Calendar.DATE, -1);
        Date date = cal.getTime();
        return getDateFormat(DATE_FORMAT_19).format(date);
    }

    /**
     * 获取下一年时间 不去 -1天
     *
     * @param cinTime
     * @return
     */
    public static String getNextYearNotSubtract(String cinTime) {
        Calendar cal = Calendar.getInstance();
        try {
            cal.setTime(getDateFormat(DATE_FORMAT_19).parse(cinTime));
        } catch (ParseException e) {
            return "";
        }
        cal.add(Calendar.YEAR, 1);
        cal.add(Calendar.DATE, 0);
        Date date = cal.getTime();
        return getDateFormat(DATE_FORMAT_19).format(date);
    }

    /**
     * 获取下年的时间  根据天数来计算差几天
     * @param cinTime
     * @param num
     * @return
     */

    public static String getNextYearDate(String cinTime, int num) {
        Calendar cal = Calendar.getInstance();
        try {
            cal.setTime(getDateFormat(DATE_FORMAT_19).parse(cinTime));
        } catch (ParseException e) {
            return "";
        }
        cal.add(Calendar.YEAR, num);
        Date date = cal.getTime();
        return getDateFormat(DATE_FORMAT_19).format(date);
    }

    /**
     * 获取上个月的今天
     * 
     * @return
     */
    public static Date getThisDayLastMonth() {
        Calendar c = Calendar.getInstance();
        c.setTime(getCurrentDate());
        c.add(Calendar.MONTH, -1);
        return c.getTime();
    }
    
    @Deprecated
    public final static SimpleDateFormat dateformat_hour_min_5 = new SimpleDateFormat("HH:mm");
    @Deprecated
    public static final SimpleDateFormat dateformat_min_sec = new SimpleDateFormat("mm:ss");
    @Deprecated
    public static final SimpleDateFormat dateformat_6 = new SimpleDateFormat("yyyyMM");
    @Deprecated
    public static final SimpleDateFormat dateformat_8 = new SimpleDateFormat("yyyyMMdd");
    @Deprecated
    public static final SimpleDateFormat dateformat_10 = new SimpleDateFormat("yyyy-MM-dd");
    @Deprecated
    public static final SimpleDateFormat dateformat_13 = new SimpleDateFormat("yyyy-MM-dd HH");
    @Deprecated
    public static final SimpleDateFormat dateformat_18 = new SimpleDateFormat(DATE_FORMAT_19);
    @Deprecated
    public static final SimpleDateFormat dateformat_14 = new SimpleDateFormat("yyyyMMddHHmmss");
    @Deprecated
    public static final SimpleDateFormat dateformat_11_in_chinese = new SimpleDateFormat("yyyy年MM月dd日");
    @Deprecated
    public static final SimpleDateFormat dateformat_17_in_chinese = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
    /**
     * 实际上是19位 所以用19 误导
     */
    @Deprecated
    public static final String DATE_FORMAT_18 = DATE_FORMAT_19;
}

